TML-2787: M:N slice 3 — nested writes through the junction (DRAFT — type-level disable pending decision)#683
Draft
tensordreams wants to merge 6 commits into
Draft
Conversation
Write slice: connect/disconnect/create through the junction + required-payload .create disable (types+runtime). 4 dispatches (write path / required-payload fixture / type+runtime disable / integration). Type-disable feasibility risk pre-named with a halt. Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net>
Replace the partitionByOwnership N:M rejection guard with a junctionOwned bucket. connect/disconnect/create over a through relation now resolve to junction INSERT/DELETE (create = target-insert then link) in both the create() and update() graph flows, after the parent PK is known. Composite keys are AND-ed across all parent/child column pairs; disconnect stays update()-only. Flip the rejection unit test to a positive junction-DML assertion and add connect/disconnect/create coverage for both flows. Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net>
… with required payload column; re-emit contract
Adds a Role model (id, name) and UserRole junction (userId, roleId,
level NOT NULL no-default) to the sql-orm-client integration fixture,
plus a User.roles manyToMany relation through UserRole. The required
non-FK column `level` in UserRole exercises the requiredPayloadColumns
path in resolveThrough, which D3 uses to disable direct .create for
junctions with required payload.
Re-emits contract.json + contract.d.ts for both the integration test
copy and the package-local copy (pgvector refs stripped). Change is
additive: existing models and User.tags relation are unchanged.
Verified: resolveThrough('user_roles') → requiredPayloadColumns=['level']
(NOT NULL ∧ no default ∧ not FK).
Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net>
…umns exist Throw a clear runtime error when a nested `.create()` targets an M:N relation whose junction table has non-FK NOT-NULL columns with no default (i.e. `requiredPayloadColumns` is non-empty). The error names the relation, the offending column(s), and points to the junction model / SQL builder as the supported alternative. `connect` and `disconnect` are unaffected — they only touch the FK pair. Pure junctions (no required payload) pass through the create path as before. Adds `requiredPayloadColumns` to the local `JunctionThrough` interface and copies it from the already-resolved `relation.through` in `getRelationDefinitions`. Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net>
…finish write integration tests Both `connect` and `create` write a bare junction row the M:N sugar can't complete when the junction has required non-FK columns (e.g. `user_roles.level NOT NULL`). Extend the runtime guard in `applyJunctionOwnedMutation` to cover `connect` in addition to `create`; `disconnect` (DELETE path) is unaffected. Guard message is unified: "Cannot `<op>` on relation `<rel>`: its junction `<table>` has required column(s) `<col>` the relation API can't populate. Use the `<Model>` model directly or the SQL builder." Unit test that previously asserted connect-on-User.roles succeeds is flipped to assert rejection. Integration tests are fully enabled (no it.skip); the new test asserts connect on User.roles throws the guard, while pure-junction (User.tags) connect/create/disconnect paths continue to work end-to-end. Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net>
Contributor
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
size-limit report 📦
|
@prisma-next/extension-author-tools
@prisma-next/mongo-runtime
@prisma-next/family-mongo
@prisma-next/sql-runtime
@prisma-next/family-sql
@prisma-next/extension-arktype-json
@prisma-next/middleware-cache
@prisma-next/mongo
@prisma-next/extension-paradedb
@prisma-next/extension-pgvector
@prisma-next/extension-postgis
@prisma-next/postgres
@prisma-next/sql-orm-client
@prisma-next/sqlite
@prisma-next/target-mongo
@prisma-next/adapter-mongo
@prisma-next/driver-mongo
@prisma-next/contract
@prisma-next/utils
@prisma-next/config
@prisma-next/errors
@prisma-next/framework-components
@prisma-next/operations
@prisma-next/ts-render
@prisma-next/contract-authoring
@prisma-next/ids
@prisma-next/psl-parser
@prisma-next/psl-printer
@prisma-next/cli
@prisma-next/cli-telemetry
@prisma-next/emitter
@prisma-next/migration-tools
prisma-next
@prisma-next/vite-plugin-contract-emit
@prisma-next/mongo-codec
@prisma-next/mongo-contract
@prisma-next/mongo-value
@prisma-next/mongo-contract-psl
@prisma-next/mongo-contract-ts
@prisma-next/mongo-emitter
@prisma-next/mongo-schema-ir
@prisma-next/mongo-query-ast
@prisma-next/mongo-orm
@prisma-next/mongo-query-builder
@prisma-next/mongo-lowering
@prisma-next/mongo-wire
@prisma-next/sql-contract
@prisma-next/sql-errors
@prisma-next/sql-operations
@prisma-next/sql-schema-ir
@prisma-next/sql-contract-psl
@prisma-next/sql-contract-ts
@prisma-next/sql-contract-emitter
@prisma-next/sql-lane-query-builder
@prisma-next/sql-relational-core
@prisma-next/sql-builder
@prisma-next/target-postgres
@prisma-next/target-sqlite
@prisma-next/adapter-postgres
@prisma-next/adapter-sqlite
@prisma-next/driver-postgres
@prisma-next/driver-sqlite
commit: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Slice 3 (final) of the SQL ORM: Many-to-Many End to End project (Linear project). Nested
connect/disconnect/createthrough the junction + the required-payload safety rail.Overview
db.orm.User.update/create({ tags: (t) => t.connect/disconnect/create(...) })now routes to theUserTagjunction (INSERT / DELETE / target-insert+link), under bothcreate()andupdate(). TheN:M not supported yetguard is gone. Junctions with a required non-FK payload column cant be written through the sugar, socreateandconnecton them are disabled with a clear error (disconnect stays).Changes (5 commits)
74a778816— runtime junction write path:partitionByOwnershipgains ajunctionOwnedbucket (keyed onthroughpresence); connect→INSERT, disconnect→DELETE, create→target-insert+link, both flows, composite-key AND-ed; the rejection unit test flipped positive. (getRelationDefinitionsnow carriesthrough.)926bdc849— required-payload fixture:User ↔ RoleviaUserRole(user_id, role_id, level NOT NULL)(canonical CLI emit).3bccd80b3— runtime guard: nestedcreateon a required-payload junction throws.e6c641811— design correction (decision Remove SQL -> Runtime dependency #9): extended the guard toconnecttoo (connect also INSERTs a junction row it cant complete → DB NOT-NULL violation), flipped the unit test, finished the 10 write integration tests.Integration tests (per the project standard)
mn-nested-write.test.ts— 10 tests, no skips: connect/create on the pureUser.tagsjunction with whole-row readback viainclude(tags), bothcreate()+update()flows;disconnect; connect AND create onUser.rolesthrow the guard;disconnectonUser.rolesworks. Whole-rowtoEqual, explicit.selectin most, ≥1 implicit/default selection.AC status
create+connecton required-payload junctions: ✅ done + tested. Type-level disable: deferred — see below.⚠ Open decision (blocks marking this slice done)
The type-level
.createdisable cant be built as specified: the generatedcontract.d.tsrelation type carries onlyto/cardinality/on, notthrough— so a conditional type cant see which model is the junction or that it has a required column.requiredPayloadColumnsexists only at runtime. Honouring the type-level disable needs the contract.d.tstype emitter to carrythrough(a contract-surface change reaching into slice-0 territory). Options (full detail inwip/unattended-decisions.md#8):.d.tsemitter to emitthrough, then a follow-up adds the conditional-type disable + negative type test;requiredPayloadColumns/hasRequiredPayloadmarker into the typed relation;I shipped the runtime guard and left this for you. Once you pick (a)/(b), a small follow-up dispatch completes the type-level disable.
Notes
connect-disabled-on-required-payload was a mid-flight spec correction (the original spec wrongly assumed connect was FK-pair-only safe). The reverseTag.users/Role.usersdirections are deferred (one-directional fixture, decision #3). Refs: TML-2787.